#include "BoolManager.h"
#include "PMeshManager.h"
#include <iostream>

std::string MeshProcessing::BoolManager::ERROR_MESSAGE = "";

MeshProcessing::PMesh* MeshProcessing::BoolManager::intersection(Handle mesh1, Handle mesh2, bool bRemoveDuplicates, bool bRemoveDegenerate) {
	PMesh* meshA = (PMesh*)mesh1;
	PMesh* meshB = (PMesh*)mesh2;

	auto out = new PMesh();

	doIntersection((PMesh*)mesh1, (PMesh*)mesh2, out, bRemoveDuplicates, bRemoveDegenerate);
	return out;
}
MeshProcessing::PMesh* MeshProcessing::BoolManager::difference(Handle mesh1, Handle mesh2, bool bRemoveDuplicates, bool bRemoveDegenerate) {
	PMesh* meshA = (PMesh*)mesh1;
	PMesh* meshB = (PMesh*)mesh2;

	auto out = new PMesh();

	doDifference((PMesh*)mesh1, (PMesh*)mesh2, out, bRemoveDuplicates, bRemoveDegenerate);
	return out;
}
MeshProcessing::PMesh* MeshProcessing::BoolManager::unions(Handle mesh1, Handle mesh2, bool bRemoveDuplicates, bool bRemoveDegenerate) {
	PMesh* meshA = (PMesh*)mesh1;
	PMesh* meshB = (PMesh*)mesh2;

	auto out = new PMesh();

	doUnion((PMesh*)mesh1, (PMesh*)mesh2, out, bRemoveDuplicates, bRemoveDegenerate);
	return out;
}

bool MeshProcessing::BoolManager::doIntersection(PMesh* mesh1, PMesh* mesh2, PMesh* out, bool bRemoveDuplicates, bool bRemoveDegenerate)
{
	if (bRemoveDuplicates) {
		mesh1->preprocessMesh(bRemoveDegenerate);
		mesh2->preprocessMesh(bRemoveDegenerate);
	}

	PMesh* res = new PMesh();
	try {
		computeIntersection(*mesh1, *mesh2, res);
	}
	catch (const char* msg) {
		ERROR_MESSAGE = std::string(msg);
		freeCorkTriMesh(res);
		delete res;
		return false;
	}

	out->setIndices(res->getNumIndices(), res->getIndices());
	out->setVertices(res->getNumVertices(), res->getVertices());

	freeCorkTriMesh(res); // Deallocate the dll heap memory.
	delete res;
	return true;
}
bool MeshProcessing::BoolManager::doUnion(PMesh* mesh1, PMesh* mesh2, PMesh* out, bool bRemoveDuplicates, bool bRemoveDegenerate)
{
	if (bRemoveDuplicates) {
		mesh1->preprocessMesh(bRemoveDegenerate);
		mesh2->preprocessMesh(bRemoveDegenerate);
	}

	PMesh* res = new PMesh();
	try {
		computeUnion(*mesh1, *mesh2, res);
	}
	catch (const char* msg) {
		ERROR_MESSAGE = std::string(msg);
		freeCorkTriMesh(res);
		delete res;
		return false;
	}

	out->setIndices(res->getNumIndices(), res->getIndices());
	out->setVertices(res->getNumVertices(), res->getVertices());

	freeCorkTriMesh(res); // Deallocate the dll heap memory.
	delete res;
	return true;
}
bool MeshProcessing::BoolManager::doDifference(PMesh* mesh1, PMesh* mesh2, PMesh* out, bool bRemoveDuplicates, bool bRemoveDegenerate) {
	if (bRemoveDuplicates) {
		mesh1->preprocessMesh(bRemoveDegenerate);
		mesh2->preprocessMesh(bRemoveDegenerate);
	}

	PMesh* res = new PMesh();
	try {
		computeDifference(*mesh1, *mesh2, res);
	}
	catch (const char* msg) {
		ERROR_MESSAGE = std::string(msg);
		freeCorkTriMesh(res);
		delete res;
		return false;
	}

	out->setIndices(res->getNumIndices(), res->getIndices());
	out->setVertices(res->getNumVertices(), res->getVertices());

	freeCorkTriMesh(res); // Deallocate the dll heap memory.
	delete res;
	return true;

}
bool MeshProcessing::BoolManager::checkSolid(PMesh* mesh, bool bRemoveDuplicates, bool bRemoveDegenerate)
{
	if (bRemoveDuplicates) {
		mesh->preprocessMesh(bRemoveDegenerate);
	}

	return isSolid(*mesh);
}

std::string MeshProcessing::BoolManager::getErrorMessage()
{
	return ERROR_MESSAGE;
}
